using System;
using System.Collections.Generic;
using System.Linq;
using Cysharp.Threading.Tasks;
using Light;
using Light.Assets.Scripts.EventManager;
using UnityEngine;
using Weapons.Components;

namespace Weapons
{
    /// <summary>
    ///     ����Player�ϵ�״̬������ֹ�ڹ���״̬���л�����
    /// </summary>
    public class WeaponGenerator : MonoBehaviour
    {
        [SerializeField] private NewWeapon weapon;
        [SerializeField] private WeaponType weaponType;
        [field: SerializeField] private WeaponDataSO data;
        private readonly List<WeaponComponent> componentAddedToWeapon = new();

        private Animator anim;

        private List<WeaponComponent> componentAlreadyOnWeapon = new();

        private List<Type> componentDependencies = new();

        private PlayerSM playerSM;

        private void Awake()
        {
            EventManager.Register<WeaponChangeEvent>(ChangeWeaponAsync);
            EventManager.Register<PlayerRegisterEvent>(OnPlayerRegisterEventHandle);
        }

        private void Start()
        {
            anim = GetComponentInChildren<Animator>();
            GenerateWeapon(data);
        }

        /// <summary>
        ///     ��¼���״̬����ֹ�ڹ���ģʽ���л�����
        /// </summary>
        /// <param name="event"></param>
        private void OnPlayerRegisterEventHandle(PlayerRegisterEvent @event)
        {
            playerSM = @event.transform.GetComponent<Player>().StateMechine;
        }

        public async void ChangeWeaponAsync(WeaponChangeEvent evt)
        {
            var it = evt.item as WeaponItemSO;
            data = it.weaponDataSO;

            if (playerSM.CurrentState is PlayerAttackState)
                await UniTask.WaitUntil(() => playerSM.CurrentState is not PlayerAttackState);

            GenerateWeapon(data);

            //evt.Dispose();
        }


        public void GenerateWeapon(WeaponDataSO data)
        {
            weapon.SetCurrentAttackCounter(0);
            weapon.SetData(data);
            componentAlreadyOnWeapon.Clear();
            componentAddedToWeapon.Clear();
            componentDependencies.Clear();

            componentAlreadyOnWeapon = GetComponents<WeaponComponent>().ToList();
            componentDependencies = data.GetAllDependencies();

            foreach (var dependency in componentDependencies)
            {
                if (componentAddedToWeapon.FirstOrDefault(component => component.GetType() == dependency)) continue;

                var weaponComponent =
                    componentAlreadyOnWeapon.FirstOrDefault(component => component.GetType() == dependency);

                if (weaponComponent == null) weaponComponent = gameObject.AddComponent(dependency) as WeaponComponent;

                weaponComponent.Init();
                componentAddedToWeapon.Add(weaponComponent);
            }

            var componentsToRemove = componentAlreadyOnWeapon.Except(componentAddedToWeapon); //learn point

            foreach (var item in componentsToRemove) Destroy(item);

            anim.runtimeAnimatorController = data.AnimatorController;
        }
    }
}